# 此接口已经废弃，但仍可以用来测试多个文件同时上传，仅供测试用


import bz2
import gzip
import json
import os
import requests
import sys
import tarfile
import zipfile
from requests.auth import HTTPBasicAuth
from application import db
from pyorthanc import find, Orthanc
orthanc = Orthanc('http://localhost:8042',
                  username='orthanc', password='orthanc')

IMPORTED_STUDIES = set()
COUNT_ERROR = 0
COUNT_DICOM = 0
COUNT_JSON = 0


class Patient(db.Model):
    __tablename__ = 'patient'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255, 'utf8_general_ci'), info='姓名')
    sex = db.Column(db.String(4, 'utf8_general_ci'), info='性别')
    age = db.Column(db.String(255), info='年龄')
    pid = db.Column(db.String(255), index=True, info='患者编号') 
    borntime = db.Column(db.DateTime, info='出生日期')
    hospital = db.Column(db.String(255), info='医院名')

    def __init__(self,name,sex,age,pid,hospital,borntime):
        self.sex = sex
        self.pid = pid
        self.name = name
        self.age = age
        self.hospital = hospital
        self.borntime = borntime
class Mri(db.Model): 
    __tablename__ = 'mri'
 
    id = db.Column(db.Integer, primary_key=True)
    fid = db.Column(db.String(255), unique=True, info='MRI的唯一F号')
    patient_id = db.Column(db.ForeignKey('patient.id', ondelete='RESTRICT', onupdate='RESTRICT'), index=True, info='用外键来对应患者的id（患者主键索引）减少数据冗余')
    study_id = db.Column(db.String(255), unique=True,info='studyid')
    
    device = db.Column(db.String(255, 'utf8_general_ci'), info='成像设备')
    modality = db.Column(db.String(255, 'utf8_general_ci'), info='模态个数')
    slice = db.Column(db.Integer, info='切片个数')
    
    check_date = db.Column(db.DateTime, info='检查日期')
    complaints = db.Column(db.Text(collation='utf8_general_ci'), info='主诉')
    notes = db.Column(db.Text, info='备注')
    
    ai_invasion = db.Column(db.String(10, 'utf8_general_ci'), info='ai脑侵袭')
    ai_level = db.Column(db.String(10, 'utf8_general_ci'), info='ai分级')
    
    operation_date = db.Column(db.DateTime, info='手术日期')
    Lesion_site = db.Column(db.String(255), info='病变部位')
    arachnoid = db.Column(db.String(40, 'utf8_general_ci'), info='蛛网膜界面破坏')
    simpson = db.Column(db.String(40, 'utf8_general_ci'), info='辛普森分级')
    adhesions = db.Column(db.String(40, 'utf8_general_ci'), info='黏连')
    
    subtype = db.Column(db.String(40, 'utf8_general_ci'), info='病例亚型')
    patholog_invasion = db.Column(db.String(255),info='脑侵袭')
    pathology_level = db.Column(db.String(255),info='分级')
    pathology_valueadded = db.Column(db.String(255, 'utf8_general_ci'), info='增值指数')
    inv_consistence = db.Column(db.String(4, 'utf8_general_ci'), info='脑侵袭是否一致')
    level_consistence = db.Column(db.String(4, 'utf8_general_ci'), info='分级是否一致')
    
    patient = db.relationship('Patient', primaryjoin='Mri.patient_id == Patient.id', backref='mris')

    def __init__(self,fid,patient_id,study_id,check_date,device,modality):
        self.fid = fid
        self.patient_id = patient_id
        self.study_id = study_id
        self.check_date = check_date
        self.device = device
        self.modality = modality
global MAPPING_TABLE
MAPPING_TABLE={}


def IsJson(content):
    try:
        if (sys.version_info >= (3, 0)):
            json.loads(content.decode())
            return True
        else:
            json.loads(content)
            return True
    except:
        return False


def UploadBuffer(url,username,password,dicom):
    global IMPORTED_STUDIES
    
    global COUNT_ERROR
    global COUNT_DICOM
    global COUNT_JSON

    if IsJson(dicom):
        COUNT_JSON += 1
        return
    
    auth = HTTPBasicAuth(username, password)
    r = requests.post('%s/instances' % url, auth = auth, data = dicom)

    try:
        r.raise_for_status()
    except:
        COUNT_ERROR += 1
        print('  not a valid DICOM file, ignoring it')
        return

    info = r.json()
    COUNT_DICOM += 1
    # 上传完毕

    # 需要构建一个 study id 和study instance id的映射表
    if (isinstance(info, dict) and
        not info['ParentStudy'] in IMPORTED_STUDIES):
        IMPORTED_STUDIES.add(info['ParentStudy'])
        
        
        
        r2 = requests.get('%s/instances/%s/tags?short' % (url, info['ID']),
                          auth = auth)
        r2.raise_for_status()
        tags = r2.json()
  
        print('')
        print('New imported study:')
        print('  Orthanc ID of the patient: %s' % info['ParentPatient'])
        print('  Orthanc ID of the study: %s' % info['ParentStudy'])
        print('  DICOM Patient ID: %s' % (
            tags['0010,0020'] if '0010,0020' in tags else '(empty)'))
        print('  DICOM Study Instance UID: %s' % (
            tags['0020,000d'] if '0020,000d' in tags else '(empty)'))
        print('')
        
        Study_info={'PatientName': tags['0010,0010'],'sex':tags['0010,0040'],'borndate':tags['0010,0030'],'fid': tags['0008,0050'],'pid':tags['0010,0020'],'Study_id':tags['0020,000d'],'check_date':tags['0008,0020'],'hospital':tags['0008,0080'],'device':tags['0008,0070'],'modality':tags['0008,0060']} 
        print(Study_info)
        pid = Study_info['pid']
        study_id = Study_info['Study_id']
        fid = Study_info['fid']
        borndate = Study_info['borndate']
        check_date = Study_info['check_date']
        name = Study_info['PatientName']
        sex = Study_info['sex']
        big=int(check_date[:4])
        small=int(borndate[:4])
        age=big-small
        hospital = Study_info['hospital']
        device=Study_info['device']
        modality=Study_info['modality']
        print(tags['0020,0010'])
        # print('****************************')
        # print(pid,fid,borndate,check_date,name,sex,hospital,device,modality)
        
        # 存储当前的study id 和 study instance id 
        MAPPING_TABLE[info['ParentStudy']] = study_id 
        
        
        # 根据检查病人是否存在
        patient = Patient.query.filter(Patient.pid == pid).first() 
        #patient = db.session.query(Patient).filter(Patient.pid == pid).first()
        if patient is None:
            #不存在则添加
            newpatient = Patient(name,sex,age,pid,hospital,borndate)
            print('1:',newpatient)
            db.session.add(newpatient)
            db.session.commit()
            patient = Patient.query.filter(Patient.pid == pid).first()
        #添加mri记录
            # 检查mri时候存在，不过没必要数据库设置F号唯一即可，重复插入会报错
        iffid = Patient.query.filter(Mri.fid == fid).first()  
        if iffid is None:   
            newmri = Mri(fid,patient.id,study_id,check_date,device,modality)
            print(Mri.check_date)
            print('2:',newmri)
            db.session.add(newmri)
            db.session.commit()
        
def UploadFile(url,username,password,path):
    with open(path, 'rb') as f:
        dicom = f.read()
        print('Uploading: %s (%dMB)' % (path, len(dicom) / (1024 * 1024)))

        UploadBuffer(url,username,password,dicom)

        
def UploadBzip2(url,username,password,path):
    with bz2.BZ2File(path, 'rb') as f:
        dicom = f.read()
        print('Uploading: %s (%dMB)' % (path, len(dicom) / (1024 * 1024)))

        UploadBuffer(url,username,password,dicom)
        
def UploadGzip(url,username,password,path):
    with gzip.open(path, 'rb') as f:
        dicom = f.read()
        print('Uploading: %s (%dMB)' % (path, len(dicom) / (1024 * 1024)))

        UploadBuffer(url,username,password,dicom)
        
def UploadTar(url,username,password,path, decoder):
    print('Uncompressing tar archive: %s' % path)
    with tarfile.open(path, decoder) as tar:
        for item in tar:
            if item.isreg():
                f = tar.extractfile(item)
                dicom = f.read()
                f.close()
                print('Uploading: %s (%dMB)' % (item.name, len(dicom) / (1024 * 1024)))
                UploadBuffer(url,username,password,dicom)
        
def UploadZip(url,username,password,path):

    print('Uncompressing ZIP archive: %s' % path)
    with zipfile.ZipFile(path, 'r') as zip:
        for item in zip.infolist():
            # WARNING - "item.is_dir()" would be better, but is not available in Python 2.7
            if item.file_size > 0:
                dicom = zip.read(item.filename)
                print('Uploading: %s (%dMB)' % (item.filename, len(dicom) / (1024 * 1024)))
                UploadBuffer(url,username,password,dicom)
                

def DecodeFile(url,username,password,path):
    extension = os.path.splitext(path) [1]
    
    if path.endswith('.tar.bz2'):
        UploadTar(url,username,password,path, 'r:bz2')
    elif path.endswith('.tar.gz'):
        UploadTar(url,username,password,path, 'r:gz')        
    elif extension == '.zip':
        UploadZip(url,username,password,path)
    elif extension == '.tar':
        UploadTar(url,username,password,path, 'r')
    elif extension == '.bz2':
        UploadBzip2(url,username,password,path)
    elif extension == '.gz':
        UploadGzip(url,username,password,path)
    else:
        UploadFile(url,username,password,path)
                
def upload_slice():
  for key,value in MAPPING_TABLE.items():
    slice_count=0
    print('studies:',key)
    patients = find(
          orthanc=orthanc,
          study_filter=lambda s: s.id_ == key
      )
    for patient in patients:
      print(patient.name) 
      # dic=patient.get_main_information()
      # print(dic) 
      for study in patient.studies:
        if study.id_ == key:
          # dic=study.get_main_information()
          # print(dic)
          for series in study.series:
              for instance in series.instances:
                # dic=instance.get_main_information()
                # print(dic)
                slice_count+=1
                
    # 上传slice到mysql
    Mri.query.filter(Mri.study_id == value).update({'slice': slice_count})
    # Mri.query.filter(Mri.study_id == value).update({'slice': slice_count})
    # 提交会话
    db.session.commit()
    

   
   
def upload2orthanc(url='http://localhost:8042',username='orthanc',password='orthanc',path=''): 
                
    if os.path.isfile(path):
        DecodeFile(url,username,password,path)
    elif os.path.isdir(path):
        for root, dirs, files in os.walk(path):
            for name in files:
                DecodeFile(url,username,password,os.path.join(root, name))
    else:
        raise Exception('Missing file or directory: %s' % path)
    # 更新slice信息
    upload_slice()
    
    print('')
    if COUNT_ERROR == 0:
        print('SUCCESS:')
    else:
        print('WARNING:')
        
    print('  %d DICOM instances properly imported' % COUNT_DICOM)
    print('  %d DICOM studies properly imported' % len(IMPORTED_STUDIES))
    print('  %d JSON files ignored' % COUNT_JSON)
    print('  Error in %d files' % COUNT_ERROR)
 
 
if __name__ == '__main__':   
    upload2orthanc(path=r"C:\Users\AMYGDALA\Desktop\data\WANG_XU")

